package org.zjt.demo.config;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.annotation.*;
import org.zjt.demo.common.ExceptionApiHandler;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by zhang on 2017/3/1.
 */
@Configuration
@EnableAspectJAutoProxy
@Aspect
@SuppressWarnings("all")
public class AspectConfig {

    private static final Logger LOGGER =Logger.getLogger(AspectConfig.class);
    private static final Map<String,AtomicLong> ACCESS_COUNT=new ConcurrentHashMap<>();
    private static final String PACKAGE_SEPARATOR=".";




    @Before("execution(* org.zjt.demo.dao..*.*(..))")
    public void before(){
        LOGGER.info("--------dao-before------------");
    }

    @After("execution(* org.zjt.demo.dao..*.*(..))")
    public void after(){
        LOGGER.info("--------dao-after------------");
    }

	@Around("execution(* org.zjt.demo.api..*.*(..))")
	public Object  around(ProceedingJoinPoint joinpoint)throws java.lang.Throwable{
	    Long startTime=System.currentTimeMillis();
        Object[] args = joinpoint.getArgs();
        Object result=joinpoint.proceed(args);
        String methodName=joinpoint.getSignature().getName();
        String DeclaringTypeName=joinpoint.getSignature().getDeclaringTypeName();
        Long endTime=System.currentTimeMillis();
        if(!ACCESS_COUNT.containsKey(DeclaringTypeName+PACKAGE_SEPARATOR+methodName))
            ACCESS_COUNT.putIfAbsent(DeclaringTypeName+PACKAGE_SEPARATOR+methodName,new AtomicLong(1));  //同步的
        else
            ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).incrementAndGet();
        LOGGER.info(String.format("执行%s.%s()  参数:%s  耗时:%s（毫秒）  第%s次调用",DeclaringTypeName,methodName, JSONObject.toJSONString(args),(endTime-startTime),ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).get()));
        if (endTime-startTime > 1000)
            LOGGER.error(String.format("执行%s.%s()  参数:%s  耗时:%s（毫秒）  第%s次调用",DeclaringTypeName,methodName, JSONObject.toJSONString(args),(endTime-startTime),ACCESS_COUNT.get(DeclaringTypeName+PACKAGE_SEPARATOR+methodName).get()));
        return result;
	}

    //抛出异常后处理
    @AfterThrowing(throwing="ex",pointcut="execution(* org.zjt.demo.api..*.*(..))")
    public void AfterExcepter(Throwable ex){
        LOGGER.error(String.format("---------抛出异常AfterExcepter:%s------------",ex));
        LOGGER.error(ExceptionApiHandler.getExceptionStack(ex));
    }

}